<?php
/* vim: set expandtab tabstop=2 shiftwidth=2 softtabstop=2 textwidth=150 number: */

/**
 * Classe Veiculo
 *
 * ...
 *
 * PHP versão 5
 *
 * LICENÇA: Este arquivo fonte esta sob o termos da licença MIT.
 *
 * @package   scuf.model
 * @author    Rodrigo Casara <rodrigocasara@gmail.com>
 * @copyright 2012 Rodrigo Casara
 * @license   MIT License (http://www.opensource.org/licenses/mit-license.php)
 * @version   SVN: $Id$
 * @link
 * @since     SCUF(tm) v 1.0.0
 */

App::uses('AppModel', 'Model');
App::uses('File', 'Utility');
App::uses('Utils', 'Lib');

/**
 * Veiculo
 *
 * {@inheritdoc}
 */
class Veiculo extends AppModel {

  /**
   * Regras de validação
   *
   * @var array
   */
  public $validate = array(
    'pessoa_id' => array(
      'numeric' => array(
        'rule' => array('numeric'),
        'message' => 'Pessoa inválida'
      ),
    ),
    'descricao' => array(
      'obrigatorio' => array(
        'rule' => array('notempty'),
        'message' => 'Obrigatório'
      ),
    ),
    'placa' => array(
      'obrigatorio' => array(
        'rule' => array('notempty'),
        'message' => 'Obrigatório'
      ),
      'placa_valida' => array(
        'rule' => '/^[A-Z]{3}[0-9]{4}$/',
        'message' => 'Placa inválida'
      ),
    ),
    'ano' => array(
      'numeric' => array(
        'rule' => array('numeric'),
        'message' => 'Ano inválido'
      ),
      'escala_ano' => array(
        'rule' => array('range', 1950, 2080),
        'message' => 'Ano inválido'
      ),
    ),
    'capacidade' => array(
      'numeric' => array(
        'rule' => array('numeric'),
        'message' => 'Capacidade inválida'
      ),
      'capacidade_minima' => array(
        'rule' => array('range', 2, 32767),
        'message' => 'Um veículo deve possuir a capacidade mínima de dois lugares'
      ),
    ),
    'cor' => array(
      'obrigatorio' => array(
        'rule' => array('notempty'),
        'message' => 'Obrigatório'
      ),
    ),
    'fotografia' => array(
        'erros_de_upload' => array(
            'rule' => array('errosDeUpload')
            // 'message' será setado pela função de validação em caso de erro.
        ),
        'image' => array(
            'rule' => array('extension', array('jpeg', 'jpg', 'png')),
            'message' => 'Arquivo inválido'
        ),
        'tamanho_do_arquivo' => array(
            'rule' => array('tamanhoDoArquivo', '300k'),
            'message' => 'Arquivo com tamanho superior a 300 KB não permitido'
        ),
        'arquivo_valido' => array(
            'rule' => array('arquivoValido'),
            'message' => 'Arquivo inválido'
        ),
        'dimensoes_em_pixels' => array(
            'rule' => array('dimensoesEmPixels', 500, 800, false),
            'message' => 'A resolução não pode ultrapassar 500 pixels de largura por 800 pixels de altura'
        )
    )
  );

  /**
   * Campos virtuais.
   *
   * @var array
   */
  public $virtualFields = array(
    'descricao_detalhada' => "Veiculo.descricao || ' - ' || Veiculo.ano || ' - cor ' || Veiculo.cor"
  );

  /**
   * Associações "pertence à".
   *
   * @var array
   */
  public $belongsTo = array(
    'Pessoa' => array(
      'className' => 'Pessoa',
      'foreignKey' => 'pessoa_id',
      'conditions' => '',
      'fields' => '',
      'order' => ''
    )
  );

  /**
   * Associações "tem muitos".
   *
   * @var array
   */
  public $hasMany = array(
    'Viagem' => array(
      'className' => 'Viagem',
      'foreignKey' => 'veiculo_id',
      'dependent' => false,
      'conditions' => '',
      'fields' => '',
      'order' => '',
      'limit' => '',
      'offset' => '',
      'exclusive' => '',
      'finderQuery' => '',
      'counterQuery' => ''
    )
  );

  // CakePHP Callbacks {{{

  /**
   * (non-PHPdoc)
   * @see Model::beforeValidate()
   */
  public function beforeValidate() {
    // Id do usuário autenticado {{{
    $idPessoa = AuthComponent::user('id');
    if (!$idPessoa) {
      // TODO: usuário não se autenticou, fazer alguma coisa a respeito.
      //$this->validationErrors['pessoa_id'] = array('Você precisa estar logado para realizar esta operação.');
      return false;
    }
    $this->data[$this->alias]['pessoa_id'] = $idPessoa;
    //}}}
    // Formatar placa {{{
    if (isset($this->data[$this->alias]['placa'])) {
      $placa = $this->data[$this->alias]['placa'];
      $placa = mb_ereg_replace("[^A-Z0-9]", "", $placa); // Remove máscaras
      $placa = mb_convert_case($placa, MB_CASE_UPPER);   // Converte tudo para maiúsculo // TODO: não está convertendo
      $this->data[$this->alias]['placa'] = $placa;
    }
    //}}}
    return true;
  }

  /**
   * (non-PHPdoc)
   * @see Model::beforeSave()
   */
  public function beforeSave() {
    $this->data[$this->alias]['cor'] = mb_convert_case($this->data[$this->alias]['cor'], MB_CASE_LOWER);
    if (isset($this->data[$this->alias]['fotografia'])) {
      $ext = pathinfo($this->data[$this->alias]['fotografia']['name'], PATHINFO_EXTENSION);
      $origem = $this->data[$this->alias]['fotografia']['tmp_name'];
      $arquivoFotografia = new File($origem);
      $this->data[$this->alias]['fotografia'] = $this->data[$this->alias]['placa'] . "." . strtolower($ext);
      $destino = $this->obterCaminhoAbsolutoFotografia();
      if (!@move_uploaded_file($origem, $destino)) {
        // TODO: Melhorar a mensagem de erro no campo, analizar se é nessário registrar no log e avisar o admin por e-mail.
        $this->validationErrors['fotografia'] = array('Erro no upload');
        return false;
      }
      @chmod($destino, 0644);
    }
    return true;
  }

  /**
   * (non-PHPdoc)
   * @see Model::beforeDelete()
   */
  public function beforeDelete($cascade = true) {
    $this->read('fotografia', $this->id);
    return true;
  }

  /**
   * (non-PHPdoc)
   * @see Model::afterDelete()
   */
  public function afterDelete() {
    $caminhoArquivoLocal = $this->obterCaminhoAbsolutoFotografia();
    $arquivoFotografia = new File($caminhoArquivoLocal);
    if ($arquivoFotografia) {
      $arquivoFotografia->delete();
    }
  }

  //}}}

  // Métodos customizados de validação {{{

  public function errosDeUpload($dados) {
    $mensagensDeErro = array(
        UPLOAD_ERR_INI_SIZE   => 'O arquivo enviado excede a diretiva upload_max_filesize em php.ini.',
        UPLOAD_ERR_FORM_SIZE  => 'O arquivo enviado excede o tamanho em MAX_FILE_SIZE que foi especificado no formulário HTML.',
        UPLOAD_ERR_PARTIAL    => 'O arquivo foi apenas parcialmente carregado.',
        UPLOAD_ERR_NO_TMP_DIR => 'Faltando uma pasta temporária.',
        UPLOAD_ERR_CANT_WRITE => 'Falha ao gravar arquivo em disco.',
        UPLOAD_ERR_EXTENSION  => 'Arquivo de upload parou por extensão.'
    );

    if (   $dados['fotografia']['error'] !== UPLOAD_ERR_OK
        && $dados['fotografia']['error'] !== UPLOAD_ERR_NO_FILE
    ) {
      $this->validationErrors['fotografia'] = array($mensagensDeErro[$dados['fotografia']['error']]);
      return false;
    }
    return true;
  }

  public function tamanhoDoArquivo($dados, $tamanho) {
    $tamanho = Utils::obterTamanhoEmBytes($tamanho);
    if ($dados['fotografia']['size'] > $tamanho) {
      return false;
    }
    return true;
  }

  public function arquivoValido($dados) {
    $dimensoes = getimagesize($dados['fotografia']['tmp_name']);
    switch ($dimensoes[2]) {
      case IMAGETYPE_JPEG:
        $imagem = @imagecreatefromjpeg($dados['fotografia']['tmp_name']);
        break;
      case IMAGETYPE_PNG:
        $imagem = @imagecreatefrompng($dados['fotografia']['tmp_name']);
        break;
      default:
        $imagem = false;
        break;
    }
    if (!$imagem) {
      return false;
    }
    return true;
  }

  public function dimensoesEmPixels($dados, $largura, $altura, $valoresExatos = false) {
    $dimensoes = getimagesize($dados['fotografia']['tmp_name']);
    if (!$dimensoes[0] || !$dimensoes[1]) {
      return false;
    } elseif ($valoresExatos === false || $valoresExatos === null) {
      if ($dimensoes[0] > $largura || $dimensoes[1] > $altura) {
        return false;
      }
    } elseif ($dimensoes[0] !== $largura || $dimensoes[1] !== $altura) {
      return false;
    }
    return true;
  }

  //}}}

  /**
   * Descreva o método aqui ...
   * return string
   */
  public function obterCaminhoAbsolutoFotografia() {
    return Configure::read("DiretorioDeFotografiasDosCarros") . DS . $this->data[$this->alias]['fotografia'];
  }

  public function temViagensDivulgadas() {
    $totalDeViagens = $this->Viagem->find('count', array(
      'conditions' => array($this->Viagem->alias . '.veiculo_id' => $this->id)
    ));
    if ($totalDeViagens) {
      return true;
    }
    return false;
  }

}

?>